/*
 *  tropeTreeNode.h
 *  tropeProject
 *
 *  Created by Jared Schiffman on 12/5/10.
 *  Copyright 2010 Potion. All rights reserved.
 *
 */

#include "tropeTypes.h"

enum tropeSyntaxType {	TROPE_NULL_SYNTAX, TROPE_CONSTANT, TROPE_VARIABLE_DECLARATION, TROPE_VARIABLE_INSTANTIATION,
						TROPE_IF_STATEMENT, TROPE_WHILE_STATEMENT, TROPE_FOR_STATEMENT, TROPE_EXPRESSION, TROPE_CODE_BLOCK,
						TROPE_METHOD_DECLARATION, TROPE_METHOD_INSTANTIATION, TROPE_RETURN_STATEMENT, TROPE_BREAK_STATEMENT, TROPE_CONTINUE_STATEMENT,
						TROPE_OPERATOR, TROPE_VARIABLE_DECLARATION_LIST };

enum tropeChangeType { CHANGE_BASIC, CHANGE_DELETE };


class tropeTreeNode
{	
public:
	tropeTreeNode();
	~tropeTreeNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_NULL_SYNTAX; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
	
	std::string&					getName() { return name; };
	void							setName( std::string _name ) { name = _name; };

	int								numChildren() { return children.size(); };
	tropeTreeNode*					getChild( int i );
	tropeTreeNode*					getChildByName( std::string child_name );
	virtual bool					addChild( tropeTreeNode* T );								// add node
	virtual bool					insertChildAt( int index, tropeTreeNode* T );				// insert node
	virtual bool					setChildAt( int index, tropeTreeNode* T );					// set (overwrite) node

	virtual int						getNumSlots() { return 0; };								// determines slot auto-allocation

	virtual bool					allowChildAddition( tropeTreeNode* T ) { return false; };
	virtual bool					allowChildInsertion( int index, tropeTreeNode* T ) { return false; };
	virtual bool					allowChildSetting( int index, tropeTreeNode* T ) { return false; };
	virtual bool					allowChildRemoval( int index ) { return false; };
	
	virtual bool					checkSyntax() { return true; };
	virtual void					changeNotification( tropeTreeNode *node, tropeChangeType change );
	
	std::string						name;
	std::vector<tropeTreeNode*>		children;

	static tropeTreeNode *nullNode();
	
private:
	static tropeTreeNode *TROPE_NULL_NODE;
};

class tropeConstantNode : public tropeTreeNode
{
public:
	tropeConstantNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_CONSTANT; };
	virtual tropeTypeID				getReturnType() { return parsedConstantType; };
	
	tropeTypeID						parsedConstantType;
};


class tropeVariableDeclarationNode : public tropeTreeNode
{
public:
	tropeVariableDeclarationNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_VARIABLE_DECLARATION; };
	virtual tropeTypeID				getReturnType() { return variableType; };
	
	tropeTypeID						variableType;
};


class tropeVariableInstantiationNode : public tropeTreeNode
{
public:
	tropeVariableInstantiationNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_VARIABLE_INSTANTIATION; };
	virtual tropeTypeID				getReturnType() { return variableDeclaration->getReturnType(); };
	
	virtual bool					allowChildAddition( tropeTreeNode* T );
	virtual bool					checkSyntax();
	
	tropeVariableDeclarationNode*	variableDeclaration;
};


class tropeExpressionNode : public tropeTreeNode 
{
public:
	tropeExpressionNode( tropeTypeID _restrictionType = TROPE_NULL_TYPE );
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_EXPRESSION; }
	virtual tropeTypeID				getReturnType();
	
	virtual bool					allowChildAddition( tropeTreeNode* T );
	virtual bool					allowChildInsertion( int index, tropeTreeNode* T ) { return allowChildAddition(T); };
	virtual bool					allowChildSetting( int index, tropeTreeNode* T ) { return false; };
	virtual bool					allowChildRemoval( int index ) { return true; };
	virtual bool					checkSyntax();
	
	tropeTypeID						restrictionType;
};


class tropeCodeBlockNode : public tropeTreeNode 
{
public:
	tropeCodeBlockNode() { };
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_CODE_BLOCK; }
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; }
	
	virtual bool					allowChildAddition( tropeTreeNode* T );
};

class tropeLoopCodeBlockNode : public tropeCodeBlockNode {
	virtual bool					allowChildAddition( tropeTreeNode* T );
};


class tropeIfStatementNode : public tropeTreeNode
{
public:
	tropeIfStatementNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_IF_STATEMENT; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
	
	virtual int						getNumSlots() { return 2; };
	
	static const int SLOT_CONDITION = 0;
	static const int SLOT_CODE_BLOCK = 1;
};


class tropeWhileStatementNode : public tropeTreeNode 
{
public:
	tropeWhileStatementNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_WHILE_STATEMENT; }
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; }
	
	virtual int						getNumSlots() { return 2; }
	
	static const int SLOT_CONDITION = 0;
	static const int SLOT_CODE_BLOCK = 1;
};


class tropeForStatementNode : public tropeTreeNode 
{
public:
	tropeForStatementNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_FOR_STATEMENT; }
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; }
	
	virtual int						getNumSlots() { return 2; }
	
	static const int SLOT_FOR_FIRST = 0;
	static const int SLOT_FOR_SECOND = 1;
	static const int SLOT_FOR_THIRD = 2;
	static const int SLOT_FOR_CODE_BLOCK = 3;
};



class tropeReturnNode : public tropeTreeNode
{
public:
	tropeReturnNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_RETURN_STATEMENT; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
	
	virtual int						getNumSlots() { return 1; };
	
	static const int SLOT_RETURN_VALUE = 0;
};

class tropeBreakNode : public tropeTreeNode
{
public:
	tropeBreakNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_BREAK_STATEMENT; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
};

class tropeContinueNode : public tropeTreeNode
{
public:
	tropeContinueNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_CONTINUE_STATEMENT; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
};

class tropeOperatorNode : public tropeTreeNode
{
public:
	tropeOperatorNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_OPERATOR; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
};

class tropeVariableDeclarationListNode : public tropeTreeNode
{
public:
	tropeVariableDeclarationListNode() { };
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_VARIABLE_DECLARATION_LIST; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
	
	bool							allowChildAddition( tropeTreeNode* T );
};

class tropeMethodDeclarationNode : public tropeTreeNode
{
public:
	tropeMethodDeclarationNode();
	
	virtual tropeSyntaxType			getSyntaxType() { return TROPE_OPERATOR; };
	virtual tropeTypeID				getReturnType() { return TROPE_NULL_TYPE; };
	
	virtual int						getNumSlots() { return 4; };
	
	static const int SLOT_INPUT_VARIABLES = 0;
	static const int SLOT_LOCAL_VARIABLES = 1;
	static const int SLOT_RETURN_VARIABLES = 2;
	static const int SLOT_CODE_BLOCK = 3;
};



